Skip to content

fix(form): stabilize ProForm/BaseForm renders and FormItem memoization#9605

Merged
chenshuai2144 merged 1 commit intomasterfrom
cursor/form-review-performance-api-tests-964a
May 2, 2026
Merged

fix(form): stabilize ProForm/BaseForm renders and FormItem memoization#9605
chenshuai2144 merged 1 commit intomasterfrom
cursor/form-review-performance-api-tests-964a

Conversation

@chenshuai2144
Copy link
Copy Markdown
Contributor

@chenshuai2144 chenshuai2144 commented Apr 23, 2026

Summary

Form module review (performance, API shape, tests) and targeted fixes.

Performance

  • ProForm: The default contentRender was an inline function, so it was a new reference every parent re-render. That caused BaseForm’s content useMemo to recompute and remount the main form body unnecessarily. The default render is now a stable useCallback.
  • BaseForm: content’s useMemo now lists formRef (the ref object) instead of effectively depending on a stale formRef.current snapshot. useImperativeHandle for the extended formRef API no longer uses formRef.current in the dependency array (refs should not be read for dependency lists).

API / docs

  • Fixed a broken nested JSDoc on formatValues.validateFieldsReturnFormatValue in BaseForm (stray /** broke the block comment and hurt generated docs/IDE hints).

Tests

  • pnpm run tsc and pnpm exec vitest run tests/form (326 tests) pass.

Submitted by Cursor

Open in Web Open in Cursor 

Summary by CodeRabbit

发版说明

  • 重构
    • 优化了表单组件的性能,改进了内存化依赖的追踪机制,确保组件渲染更加高效。
    • 改进了表单字段属性的处理逻辑,简化了内部实现。

…rativeHandle

- ProForm: memoize default contentRender with useCallback to avoid new
  function identity every render and unnecessary BaseForm content remounts
- BaseForm: fix nested JSDoc on formatValues; useImperativeHandle deps use
  formRef instead of formRef.current; content useMemo depends on formRef
- FormItem: useDeepCompareMemo depends on child fieldProps (not duplicate
  omit() in deps array) for correct deep-compare memoization

Co-authored-by: 陈帅 <wasd2144@hotmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dad49215-5642-4679-b172-0ee898c8ccc7

📥 Commits

Reviewing files that changed from the base of the PR and between bdbf841 and dd22eaa.

📒 Files selected for processing (3)
  • src/form/BaseForm/BaseForm.tsx
  • src/form/components/FormItem/index.tsx
  • src/form/layouts/ProForm/index.tsx

📝 Walkthrough

Walkthrough

三个表单相关文件经过内存化优化:BaseForm 调整了内容渲染和指令句柄的依赖追踪;FormItem 简化了字段属性提取逻辑;ProForm 将内联的内容渲染函数改为 useCallback 包装。

Changes

表单内存化与依赖优化

Layer / File(s) Summary
依赖追踪调整
src/form/BaseForm/BaseForm.tsx
content useMemo 现在将 formRef 加入依赖列表,contentRender 接收 formRef.current 作为参数;useImperativeHandle 依赖从 formRef.current 改为 propsFormRef,改变了句柄重新计算的时机。
字段属性集中提取
src/form/components/FormItem/index.tsx
引入 childFieldProps 变量以集中提取字段属性(仅当 filedChildren 为有效元素时),memo 依赖改为直接追踪 childFieldProps 而非重复访问 filedChildren?.props?.fieldProps
回调函数 Memoization
src/form/layouts/ProForm/index.tsx
添加 useCallback 导入,将 contentRender 从内联箭头函数改为 memoized 回调(依赖为空数组),接收 itemssubmitter_form 参数后返回 fragment。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 依赖优化兔来访,内存之舞步翩翩
formRef 轻轻入掌心,callback 化作晶莹片
字段属性归一处,性能之树又焕颜 ✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/form-review-performance-api-tests-964a

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 6/8 reviews remaining, refill in 14 minutes and 48 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates JSDoc comments, refactors dependency arrays in BaseForm and FormItem, and memoizes the contentRender function in ProForm. The review feedback points out a performance regression in FormItem due to improper dependency tracking in useDeepCompareMemo and identifies an unnecessary inclusion of a stable ref object in a useMemo dependency array in BaseForm.

['onBlur', 'onChange'],
),
],
[childFieldProps],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The change to the dependency array of omitOnBlurAndOnChangeProps introduces a performance regression. By using [childFieldProps] instead of the omitted object, the useDeepCompareMemo will now trigger a re-computation whenever onBlur or onChange change (which are often unstable inline functions in React forms). The previous implementation correctly ignored these event handlers by omitting them before the deep comparison, ensuring that only changes to other field props would trigger a re-render of the child component.

Suggested change
[childFieldProps],
[omit(childFieldProps || {}, ['onBlur', 'onChange'])],

}
return wrapItems;
}, [grid, RowWrapper, items, contentRender, submitterNode]);
}, [grid, RowWrapper, items, contentRender, submitterNode, formRef]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Adding formRef to the dependency array of useMemo is unnecessary and potentially misleading. formRef is a ref object created via useRef within the component, so its reference is stable and will not trigger a re-computation of the memoized value. Furthermore, adding a ref object to dependencies does not solve "stale snapshot" issues because useMemo does not track changes to the .current property. If the intent is to ensure the latest form instance is used, accessing formRef.current inside the factory is sufficient, but it won't trigger updates if the ref is updated after the initial render.

Suggested change
}, [grid, RowWrapper, items, contentRender, submitterNode, formRef]);
}, [grid, RowWrapper, items, contentRender, submitterNode]);

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 23, 2026

Codecov Report

❌ Patch coverage is 83.33333% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 88.48%. Comparing base (bdbf841) to head (dd22eaa).
⚠️ Report is 6 commits behind head on master.

Files with missing lines Patch % Lines
src/form/components/FormItem/index.tsx 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #9605      +/-   ##
==========================================
- Coverage   88.53%   88.48%   -0.06%     
==========================================
  Files         368      368              
  Lines       11257    11259       +2     
  Branches     4157     4156       -1     
==========================================
- Hits         9966     9962       -4     
- Misses       1139     1144       +5     
- Partials      152      153       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@chenshuai2144 chenshuai2144 marked this pull request as ready for review May 2, 2026 03:13
Copilot AI review requested due to automatic review settings May 2, 2026 03:13
@chenshuai2144 chenshuai2144 merged commit 96200dc into master May 2, 2026
9 of 13 checks passed
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label May 2, 2026
@chenshuai2144 chenshuai2144 deleted the cursor/form-review-performance-api-tests-964a branch May 2, 2026 03:13
@dosubot dosubot Bot added form javascript Pull requests that update Javascript code labels May 2, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR focuses on reducing unnecessary re-renders/remounts in the form system by stabilizing render callback references and tightening React hook dependency usage, plus a small JSDoc fix for better generated docs/IDE hints.

Changes:

  • Stabilize ProForm’s default contentRender by switching from an inline function to a memoized callback.
  • Adjust BaseForm memoization/dependency handling around content and useImperativeHandle to avoid ref .current in dependency lists.
  • Fix a broken nested JSDoc block for validateFieldsReturnFormatValue documentation, and refactor FormItem memo dependencies.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/form/layouts/ProForm/index.tsx Makes default contentRender a stable callback to reduce remounts.
src/form/components/FormItem/index.tsx Refactors memoization inputs for omitted fieldProps.
src/form/BaseForm/BaseForm.tsx Fixes JSDoc and adjusts hook deps to avoid using ref.current in deps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +72 to 84
const childFieldProps = React.isValidElement(filedChildren)
? (filedChildren.props as Record<string, any>)?.fieldProps
: undefined;

const omitOnBlurAndOnChangeProps = useDeepCompareMemo(
() =>
omit(
// @ts-ignore
filedChildren?.props?.fieldProps || {},
['onBlur', 'onChange'],
),
[
omit(
// @ts-ignore
filedChildren?.props?.fieldProps || {},
childFieldProps || {},
['onBlur', 'onChange'],
),
],
[childFieldProps],
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

form javascript Pull requests that update Javascript code size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants